package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.AddressBookMapper;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.OrderService;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import com.sky.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private WebSocketServer webSocketServer;

    @Override
    public Result submitOrder(OrdersSubmitDTO dto) {
        //校验数据
        //  如果地址id对应的地址不存在，抛出异常
        AddressBook addressBook = addressBookMapper.getById(dto.getAddressBookId());
        if (addressBook == null) {
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        // 从线程中获取当前对象
        Long currentUser = BaseContext.getCurrentId();
        //购物车数据有无异常
        List<ShoppingCart> shoppingCarts = shoppingCartMapper.selectListByUser(currentUser);
        if (shoppingCarts == null || shoppingCarts.size()==0) {
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }
        //2.保存订单信息

        //构建一个orders容器
        Orders orders = new Orders();
        BeanUtils.copyProperties(dto,orders);
        //订单号 设置当前毫秒值
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        //设置订单状态为1待付款
        orders.setStatus(Orders.PENDING_PAYMENT);
        //下单人
        orders.setUserId(currentUser);
        //下单时间
        orders.setOrderTime(LocalDateTime.now());
        //设置支付状态为0未支付
        orders.setPayStatus(Orders.UN_PAID);
        //手机号
        orders.setPhone(addressBook.getPhone());
        //获取详细地址
        orders.setAddress(addressBook.getDetail());
        //获取收货人
        orders.setConsignee(addressBook.getConsignee());
        //存到数据库中
        orderMapper.insert(orders);

        //3.订单明细
        List<OrderDetail> orderDetails = new ArrayList<>();
        for (ShoppingCart shoppingCart : shoppingCarts) {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(shoppingCart,orderDetail);
            orderDetail.setOrderId(orders.getId());
            orderDetails.add(orderDetail);
        }

        orderDetailMapper.batchInserts(orderDetails);


        //4.清空购物车 根据userId
        shoppingCartMapper.deleteByUser(currentUser);

        //5.返回值
        OrderSubmitVO vo = new OrderSubmitVO();
        //主键自增还没有,数据库自增完返回 加注解@Options
        vo.setId(orders.getId());
        vo.setOrderTime(orders.getOrderTime());
        vo.setOrderAmount(orders.getAmount());
        vo.setOrderNumber(orders.getNumber());

        return Result.success(vo);
    }

    /**
     * 用户端订单分页查询
     * @param dto
     * @return
     */
    @Override
    public PageResult pageQueryH(OrdersPageQueryDTO dto) {
        //开启分页
        PageHelper.startPage(dto.getPage(),dto.getPageSize());
        OrdersPageQueryDTO od = new OrdersPageQueryDTO();
        od.setUserId(BaseContext.getCurrentId());
        od.setStatus(dto.getStatus());
        //分页条件查询
        Page<Orders> page = orderMapper.pageQueryH(od);
        //返回数据
        List<OrderVO> voList = new ArrayList<>();
        //如果订单信息不为空的话
        if (page != null && page.getTotal()>0) {
            //1.获取订单详细信息
            for (Orders order : page) {
                //获取订单id 查询订单详细信息
                Long orderId = order.getId();
                //在数据中查询订单详细信息
                List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(orderId);
                //构建一个容器copy刚查询的订单详细信息
                OrderVO vo = new OrderVO();
                BeanUtils.copyProperties(order,vo);
                //
                vo.setOrderDetailList(orderDetails);
                voList.add(vo);
            }
        }
        return new PageResult(page.getTotal(),voList);
    }

    @Override
    public OrderVO queryDetails(Long id) {
        //创建OrderVo容器
        OrderVO orderVO = new OrderVO();
        //根据id查询订单
        Orders orders = orderMapper.getById(id);
        //拷贝数据
        BeanUtils.copyProperties(orders,orderVO);
        //查询该订单下的菜品或者套餐信息
        List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(orders.getId());
        //在封装
        orderVO.setOrderDetailList(orderDetailList);
        return orderVO;
    }

    @Override
    public void cancel(Long id) {
        //从数据库中查询订单
        Orders ordersDB = orderMapper.getById(id);
        //判断订单是否存在
        if (ordersDB == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        //商家已接单，抛异常。不允许在线下取消了，必须通过给商家打电话取消
        //判断订单状态
        /*
         * 1待付款 2待接单 3已接单 4派送中 5已完成 6已取 7退款
         */
        //如果已经接单，我啊抛
        if (ordersDB.getStatus() > 2){
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        //更新订单状态、取消原因、取消时间
        //构建一个orders容器
        Orders orders = new Orders();
        //封装订单id
        orders.setId(ordersDB.getId());
        //更新订单状态
        orders.setStatus(Orders.CANCELLED);
        //取消原因
        orders.setCancelReason("客户不想要了");
        //取消时间
        orders.setCancelTime(LocalDateTime.now());
        //已经支付了，但商家还没有接单，给用户退款(这一步写一行注释就行了)，然后修改订单状态为“已取消”

        orderMapper.updateOrders(orders);

    }

    @Override
    public void repetition(Long id) {
        Long currentId = BaseContext.getCurrentId();
        //根据订单id从数据库中获取当前的订单详情
        List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(id);
        List<ShoppingCart> shoppingCarts = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetails) {
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(orderDetail,shoppingCart,"id");
            shoppingCart.setUserId(currentId);
            shoppingCart.setCreateTime(LocalDateTime.now());
            shoppingCarts.add(shoppingCart);
        }
        shoppingCartMapper.insertBatch(shoppingCarts);
    }

    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO dto) {
        //开启分页
        PageHelper.startPage(dto.getPage(),dto.getPageSize());
        //分页查询
        Page<Orders> page = orderMapper.pageQueryH(dto);
        //构建返回容器
        List<OrderVO> orderVOList = new ArrayList<>();
        //构建订单容器
        List<Orders> ordersList = page.getResult();
        //判断订单是否为空
        if (ordersList != null && ordersList.size()>0) {
            //遍历出每个订单
            for (Orders orders : ordersList) {
                OrderVO orderVO = new OrderVO();
                BeanUtils.copyProperties(orders,orderVO);

                // 查询订单菜品详情信息（订单中的菜品和数量）
                List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(orders.getId());
                // 将每一条订单菜品信息拼接字符串(流)
                List<String> orderDishList = orderDetailList.stream().map(x -> {
                    String orderDish = x.getName() + "*" + x.getNumber() + ";";
                    return orderDish;
                }).collect(Collectors.toList());

                String orderDishes =String.join("", orderDishList);
                orderVO.setOrderDishes(orderDishes);
                orderVOList.add(orderVO);
            }
        }

        //返回值
        return new PageResult(page.getTotal(),orderVOList);
    }

    @Override
    public OrderStatisticsVO statistics() {
        // 根据状态，分别查询出待接单、待派送、派送中的订单数量
        Integer toBeConfirmed = orderMapper.countStatus(Orders.TO_BE_CONFIRMED);
        Integer confirmed = orderMapper.countStatus(Orders.CONFIRMED);
        Integer deliveryInProgress =orderMapper.countStatus(Orders.DELIVERY_IN_PROGRESS);
        // 将查询出的数据封装到orderStatisticsVO中响应
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        orderStatisticsVO.setConfirmed(confirmed);
        orderStatisticsVO.setDeliveryInProgress(deliveryInProgress);
        orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
        return orderStatisticsVO;
    }

    @Override
    public void confirm(OrdersConfirmDTO confirmDTO) {
        Orders orders = new Orders();
        orders.setId(confirmDTO.getId());
        orders.setStatus(Orders.CONFIRMED);
        orderMapper.updateOrders(orders);
    }

    @Override
    public void rejection(OrdersRejectionDTO rejectionDTO) {
        //根据id查询订单
        Orders ordersDB = orderMapper.getById(rejectionDTO.getId());
        if (ordersDB == null || !ordersDB.getStatus().equals(Orders.TO_BE_CONFIRMED)) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        //支付状态
        Integer payStatus = ordersDB.getStatus();
        if (payStatus == Orders.PAID) {
            //用户已支付，需要退款
            String refund = "What can I say? 日你妈退钱！！！";
            log.info("申请退款：{}", refund);
        }
        // 拒单需要退款，根据订单id更新订单状态、拒单原因、取消时间db5_1
        Orders orders = new Orders();
        orders.setId(ordersDB.getId());
        orders.setStatus(Orders.CANCELLED);
        orders.setRejectionReason(rejectionDTO.getRejectionReason());
        orders.setCancelTime(LocalDateTime.now());

        orderMapper.updateOrders(orders);
    }

    @Override
    public void cancelW(OrdersCancelDTO cancelDTO) {
        //根据id查询订单
        Orders ordersDB = orderMapper.getById(cancelDTO.getId());
        //支付状态
        Integer payStatus = ordersDB.getStatus();
        if (payStatus == Orders.PAID) {
            //用户已支付，需要退款
            String refund = "What can I say? 日你妈退钱！！！";
            log.info("申请退款：{}", refund);
        }
        Orders orders = new Orders();
        orders.setId(ordersDB.getId());
        orders.setStatus(Orders.CANCELLED);
        orders.setCancelReason(cancelDTO.getCancelReason());
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.updateOrders(orders);
    }

    @Override
    public void delivery(Long id) {
        //根据id查询订单
        Orders ordersDB = orderMapper.getById(id);
        //校验订单是否存在，且是否为3已接单
        if (ordersDB == null || !ordersDB.getStatus().equals(Orders.CONFIRMED)) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        // 创建容器
        Orders orders = new Orders();
        orders.setId(ordersDB.getId());
        // 更新订单状态,状态转为派送中
        orders.setStatus(Orders.DELIVERY_IN_PROGRESS);
        orderMapper.updateOrders(orders);
    }

    @Override
    public void complete(Long id) {
        //根据id查询订单
        Orders ordersDB = orderMapper.getById(id);
        //校验订单是否存在，且是否为4派送中
        if (ordersDB == null || !ordersDB.getStatus().equals(Orders.DELIVERY_IN_PROGRESS)) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        // 创建容器
        Orders orders = new Orders();
        orders.setId(ordersDB.getId());
        // 修改订单状态为已完成
        orders.setStatus(Orders.COMPLETED);
        orders.setDeliveryTime(LocalDateTime.now());
        orderMapper.updateOrders(orders);
    }

    @Override
    public Result reminderOrder(Long id) {
        //查询订单信息
        Orders orders = orderMapper.getById(id);
        if (orders == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        //2. 利用WebSocket向管理端发送催单提醒
        Map<String,Object> map = new HashMap<>();
        map.put("type",2);
        map.put("orderId",orders.getId());
        map.put("content","订单号:"+orders.getNumber());
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
        return Result.success();
    }
}
